package auctionhaus

import grails.converters.JSON
import grails.gorm.DetachedCriteria
import org.springframework.dao.DataIntegrityViolationException
import grails.plugins.springsecurity.Secured
import grails.util.Environment;

class ListingController {

	static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
	/**
	 * SRV-4: Refactor your Controllers from the previous assignments to use the service methods created in this section (unit test)
	 */
	def crudService
	def jmsService
	def emailService

	/**
	 * S-2: Viewing the main landing page and the listing detail page does not require that the user be logged in
	 * 
	 */
	def index() {
		redirect(action: "list", params: params)
	}



	/**
	 * 
	 * This controller action was for Assignment 2, and can be ignored for Assignment 3
	 */
	def createBid() {

		params.remove("listing")  //this param is un-needed and causes errors.

		redirect(controller: "bid", action: "create",  params: params)
	}



	/**
	 * S-2: Viewing the main landing page and the listing detail page does not require that the user be logged in
	 *
	 */
	def list() {

		//M-2: The main landing page shows up to 5 listings at a time
		//M-3: If more than 5 listings exist, pagination links will be available to let the user page through the listings
		params.max = Math.min(params.max ? params.int('max') : 5, 100)

		def criteria
		def listingsCount

		/**
		 * S-5: Create a view called "My Listings" that shows listings created by the logged in user
		 * S-6: A logged in user can create a new listing via a simple form; newly created listings will appear in the "My Listings" view
		 */
		if(params.id){

			criteria = new DetachedCriteria(Listing).build {
				gt 'endDateTime',(new Date())
				eq 'seller.id',Long.parseLong(params['id'])
			}


			listingsCount = new DetachedCriteria(Listing).build {
				gt 'endDateTime',(new Date())
				eq 'seller.id',Long.parseLong(params['id'])
			}

			params['username'] = Customer.findById(Long.parseLong(params['id'])).username

		}
		else{

			//M-4: Only listings with a end date/time that is in the future are visible on the main page
			//M-1: The main landing page shows listings sorted by the date they were created (most recent first)
			criteria = new DetachedCriteria(Listing).build {
				gt 'endDateTime',(new Date())
			}

			//requires 2 criterias because one above doesn't like order clause
			//can't use listings.size() because params.max is set to 5.
			listingsCount = new DetachedCriteria(Listing).build {
				gt 'endDateTime',(new Date())
			}
		}

		//ordering is moved to here, so we can still sort other columns if user desires
		//defaults to dateCreated sorting.
		if(!params.containsKey('sort')){
			params['sort'] = 'dateCreated'
			params['order'] = 'desc'
		}

		List listings = criteria.list(params);

		[listingInstanceList: listings, listingInstanceTotal: listingsCount.count()]


	}


	def currentMinimumBid() {
		Listing l = Listing.findById(params['listing.id']);
		if(l==null){
			render("Please Refresh")
		}
		else{
			 render(Bid.amountFormatter(l.currentMinimumBid))
		}
	}


	/**
	 * 
	 * S-6: A logged in user can create a new listing via a simple form; newly created listings will appear in the "My Listings" view
	 * 
	 */
	@Secured(['ROLE_USER', 'ROLE_ADMIN'])
	def create() {
		[listingInstance: new Listing(params)]
	}

	@Secured(['ROLE_USER', 'ROLE_ADMIN'])
	def save() {
		def listingInstance = new Listing(params)

		if(listingInstance.validate()){
			listingInstance.currentMinimumBid = listingInstance.startingPrice
		}

		if (!crudService.createListing(listingInstance)) {
			render(view: "create", model: [listingInstance: listingInstance])
			return
		}


		flash.message = message(code: 'default.created.message', args: [
			message(code: 'listing.label', default: 'Listing'),
			listingInstance.id
		])
		redirect(action: "show", id: listingInstance.id)
	}

	/**
	 * S-2: Viewing the main landing page and the listing detail page does not require that the user be logged in
	 *
	 */
	def show() {
		def listingInstance = Listing.get(params.id)
		if (!listingInstance) {
			flash.message = message(code: 'default.not.found.message', args: [
				message(code: 'listing.label', default: 'Listing'),
				params.id
			])
			redirect(action: "list")
			return
		}

		[listingInstance: listingInstance]
	}
	
	def showPermanentDetails() {
		def listingInstance = Listing.get(params.id)
		if (!listingInstance) {
			flash.message = message(code: 'default.not.found.message', args: [
				message(code: 'listing.label', default: 'Listing'),
				params.id
			])
			redirect(action: "list")
			return
		}

		[listingInstance: listingInstance]
	}

	@Secured(['ROLE_ADMIN'])
	def edit() {
		def listingInstance = Listing.get(params.id)
		if (!listingInstance) {
			flash.message = message(code: 'default.not.found.message', args: [
				message(code: 'listing.label', default: 'Listing'),
				params.id
			])
			redirect(action: "list")
			return
		}

		[listingInstance: listingInstance]
	}

	@Secured(['ROLE_ADMIN'])
	def update() {
		def listingInstance = Listing.get(params.id)
		if (!listingInstance) {
			flash.message = message(code: 'default.not.found.message', args: [
				message(code: 'listing.label', default: 'Listing'),
				params.id
			])
			redirect(action: "list")
			return
		}

		if (params.version) {
			def version = params.version.toLong()
			if (listingInstance.version > version) {
				listingInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
						[
							message(code: 'listing.label', default: 'Listing')]
						as Object[],
						"Another user has updated this Listing while you were editing")
				render(view: "edit", model: [listingInstance: listingInstance])
				return
			}
		}

		listingInstance.properties = params


		if (!crudService.updateListing(listingInstance)) {
			render(view: "edit", model: [listingInstance: listingInstance])
			return
		}

		flash.message = message(code: 'default.updated.message', args: [
			message(code: 'listing.label', default: 'Listing'),
			listingInstance.id
		])
		redirect(action: "show", id: listingInstance.id)
	}

	@Secured(['ROLE_ADMIN'])
	def delete() {
		def listingInstance = Listing.get(params.id)
		if (!listingInstance) {
			flash.message = message(code: 'default.not.found.message', args: [
				message(code: 'listing.label', default: 'Listing'),
				params.id
			])
			redirect(action: "list")
			return
		}

		try {

			crudService.deleteListing(listingInstance)
			flash.message = message(code: 'default.deleted.message', args: [
				message(code: 'listing.label', default: 'Listing'),
				params.id
			])
			redirect(action: "list")
		}
		catch (DataIntegrityViolationException e) {
			flash.message = message(code: 'default.not.deleted.message', args: [
				message(code: 'listing.label', default: 'Listing'),
				params.id
			])
			redirect(action: "show", id: params.id)
		}
	}

	//C-3 When a listing completes it can no longer accept any more bids
/*	@Secured(['ROLE_ADMIN', 'ROLE_USER'])
	def completedListing() {
		def listingId = params['listing.id']
		flash.message = message(code: 'listing.completed.warn.message', args: [
			message(code: 'listing.label', default: 'Listing'),
			listingId
		])
		forward action: "show", id: listingId
	}*/

}
